package com.xinchuang.utils;

import com.alibaba.fastjson.JSONArray;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;

public class CheckUtil {

    /**
     * String类型通用验证方法
     *
     * @param value     输入的字段
     * @param label     输入的字段名称
     * @param isNull    检验此字段是否可以为空 true不可为空，false可以为空
     * @param min       检验此字段允许的最小长度
     * @param max       检验此字段允许的最大长度
     * @return 验证成功返回""，验证失败返回错误信息
     */
    public static String checkString(String value, String label, boolean isNull, Integer min, Integer max){
        String result = checkEmpty(value, label, isNull);
        if (StringUtils.isNotEmpty(result)){
            return result;
        }

        if (StringUtils.isNotEmpty(value)){
            if (value.length() < min || value.length() > max){
                return label + "长度应在[" + min + "," + max + "]之间-实际值：" + value;
            }
        }
        return "";
    }

    /**
     * Integer类型通用验证方法
     *
     * @param value     输入的字段
     * @param label     输入的字段名称
     * @param isNull    检验此字段是否可以为空 true不可为空，false可以为空
     * @param min       检验此字段允许的最小值
     * @param max       检验此字段允许的最大值
     * @return 验证成功返回""，验证失败返回错误信息
     */
    public static String checkInteger(Integer value, String label, boolean isNull, Integer min, Integer max){
        String result = checkEmpty(value, label, isNull);
        if (StringUtils.isNotEmpty(result)){
            return result;
        }

        if (value != null){
            if (value < min || value > max){
                return label + "大小应在[" + min + "," + max + "]之间";
            }
        }
        return "";
    }

    public static String checkBigDecimal(String value, String label, boolean isNull, String min, String max){
        String result = checkEmpty(value, label, isNull);
        if (StringUtils.isNotEmpty(result)){
            return result;
        }

        if (StringUtils.isNotEmpty(value)){
            int z = 0;
            int j = 0;
            try {
                z = new BigDecimal(value).compareTo(new BigDecimal(max));
                j = new BigDecimal(value).compareTo(new BigDecimal(min));
            }catch (NumberFormatException e){
                return "数字类型转换错误：" + value;
            }
            if ((z == 1) || (j == -1)){
                return label + "大小应在[" + min + "," + max + "]之间-实际值：" + value;
            }
        }
        return "";
    }

    /**
     * Float类型通用验证方法
     *
     * @param value     输入的字段
     * @param label     输入的字段名称
     * @param isNull    检验此字段是否可以为空 true不可为空，false可以为空
     * @param min       检验此字段允许的最小值
     * @param max       检验此字段允许的最大值
     * @return 验证成功返回""，验证失败返回错误信息
     */
    public static String checkFloat(Float value, String label, boolean isNull, Float min, Float max){
        String result = checkEmpty(value, label, isNull);
        if (StringUtils.isNotEmpty(result)){
            return result;
        }

        if (value != null){
            if (value < min || value > max){
                return label + "大小应在[" + min + "," + max + "]之间";
            }
        }
        return "";
    }

    /**
     * Double类型通用验证方法
     *
     * @param value     输入的字段
     * @param label     输入的字段名称
     * @param isNull    检验此字段是否可以为空 true不可为空，false可以为空
     * @param min       检验此字段允许的最小值
     * @param max       检验此字段允许的最大值
     * @return 验证成功返回""，验证失败返回错误信息
     */
    public static String checkDouble(Double value, String label, boolean isNull, Double min, Double max){
        String result = checkEmpty(value, label, isNull);
        if (StringUtils.isNotEmpty(result)){
            return result;
        }

        if (value != null){
            if (value < min || value > max){
                return label + "大小应在[" + min + "," + max + "]之间";
            }
        }
        return "";
    }

    /**
     * Boolean类型通用验证方法
     *
     * @param value     输入的字段
     * @param label     输入的字段名称
     * @param isNull    检验此字段是否可以为空 true不可为空，false可以为空
     * @return 验证成功返回""，验证失败返回错误信息
     */
    public static String checkBoolean(String value, String label, boolean isNull){
        String result = checkEmpty(value, label, isNull);
        if (StringUtils.isNotEmpty(result)){
            return result;
        }
        if (!"true".equals(value) && !"false".equals(value)){
            return "此数据不是boolean型：" + value;
        }
        return "";
    }

    /**
     * Date类型通用验证方法
     *
     * @param value     输入的字段
     * @param label     输入的字段名称
     * @param isNull    检验此字段是否可以为空 true不可为空，false可以为空
     * @return 验证成功返回""，验证失败返回错误信息
     */
    public static String checkDate(Date value, String label, boolean isNull){
        String result = checkEmpty(value, label, isNull);
        if (StringUtils.isNotEmpty(result)){
            return result;
        }
        return "";
    }

    /**
     * List类型通用验证方法
     *
     * @param value     输入的字段
     * @param label     输入的字段名称
     * @param isNull    检验此字段是否可以为空 true不可为空，false可以为空
     * @return 验证成功返回""，验证失败返回错误信息
     */
    public static String checkList(List value, String label, boolean isNull){
        if (isNull){
            if (value == null || value.size() < 1){
                return label + "不能为空";
            }
        }
        return "";
    }

    /**
     * File类型通用验证方法
     *
     * @param file      输入的文件对象
     * @param label     输入的字段名称
     * @param isNull    检验此字段是否可以为空 true不可为空，false可以为空
     * @param max       文件大小最大值（KB）
     * @return 验证成功返回""，验证失败返回错误信息
     */
    public static String checkFile(MultipartFile file, String label, Boolean isNull, Long max){
        String result = checkEmpty(file, label, isNull);
        if (StringUtils.isNotEmpty(result)){
            return result;
        }

        if (max != null){
            if (file != null){
                if ((file.getSize() / 1024) > max){
                    return label + "最大不能超过" + max + "KB";
                }
            }
        }
        return "";
    }
    //不检查文件的最大值
    public static String checkFile(MultipartFile file, String label, Boolean isNull){
        return checkFile(file, label, isNull, null);
    }

    /**
     * JSONArray类型通用验证方法
     *
     * @param jsonArray     输入的JSON数组
     * @param label         输入的字段名称
     * @param isNull        检验此字段是否可以为空 true不可为空，false可以为空
     * @return 验证成功返回""，验证失败返回错误信息
     */
    public static String checkJSONArray(JSONArray jsonArray, String label, boolean isNull){
        return checkJSONArray(jsonArray, label, isNull, null, 1, 1, 1, 1);
    }
    public static String checkJSONArray(JSONArray jsonArray, String label, boolean isNull, Integer arrSize, Integer nodeType, Integer paramType, Integer min, Integer max){
        String result = checkEmpty(jsonArray, label, isNull);
        if (StringUtils.isNotEmpty(result)){
            return result;
        }

        //如果类型是数组则对数组中的值进行以下判断，如果是对象数组则不需要
        if (nodeType == 2){
            if (jsonArray != null && jsonArray.size() > 0){
                for (int i = 0; i < jsonArray.size(); i++){
                    //参数类型是1则数组中是字符串否则则是数字
                    String value = jsonArray.getString(i);
                    if (paramType == 1){
                        result = checkString(value, label, false, min, max);
                    }else {
                        result = checkBigDecimal(value, label, false, min + "", max + "");
                    }
                    if (StringUtils.isNotEmpty(result)){
                        return result;
                    }
                }
            }
        }

        if (arrSize != null){
            if (jsonArray.size() > arrSize){
                return label + "数组长度" + jsonArray.size() + "大于最大值" + arrSize;
            }
        }
        return "";
    }

    /**
     * 验证邮箱
     *
     * @param email     email地址，格式：test@qq.com，zhangsan@xxx.com.cn，xxx代表邮件服务商
     * @param isNull    检验此字段是否可以为空 true不可为空，false可以为空
     * @return 验证成功返回""，验证失败返回错误信息
     */
    public static String checkEmail(String email, boolean isNull) {
        String regex = "\\w+@\\w+\\.[a-z]+(\\.[a-z]+)?";
        return commonRegex(regex, email, "邮箱", isNull);
    }

    /**
     * 验证身份证号码
     *
     * @param idCard    居民身份证号码15位或18位，最后一位可能是数字或字母
     * @param isNull    检验此字段是否可以为空 true不可为空，false可以为空
     * @return 验证成功返回""，验证失败返回错误信息
     */
    public static String checkIdCard(String idCard, boolean isNull) {
        String regex = "[1-9]\\d{13,16}[a-zA-Z0-9]{1}";
        return commonRegex(regex, idCard, "身份证号码", isNull);
    }

    /**
     * 验证手机号码（支持国际格式，+86135xxxx...（中国内地），+00852137xxxx...（中国香港））
     * @param mobile    移动、联通、电信运营商的号码段
     *<p>移动的号段：134(0-8)、135、136、137、138、139、147（预计用于TD上网卡）
     *、150、151、152、157（TD专用）、158、159、187（未启用）、188（TD专用）</p>
     *<p>联通的号段：130、131、132、155、156（世界风专用）、185（未启用）、186（3g）</p>
     *<p>电信的号段：133、153、180（未启用）、189</p>
     *
     * @param isNull    检验此字段是否可以为空 true不可为空，false可以为空
     * @return 验证成功返回""，验证失败返回错误信息
     */
    public static String checkMobile(String mobile, boolean isNull) {
        String regex = "(\\+\\d+)?1[3458]\\d{9}$";
        return commonRegex(regex, mobile, "手机号码", isNull);
    }

    /**
     * 验证固定电话号码
     *
     * @param phone 电话号码，格式：国家（地区）电话代码 + 区号（城市代码） + 电话号码，如：+8602085588447
     * <p><b>国家（地区） 代码 ：</b>标识电话号码的国家（地区）的标准国家（地区）代码。它包含从 0 到 9 的一位或多位数字，
     *  数字之后是空格分隔的国家（地区）代码。</p>
     * <p><b>区号（城市代码）：</b>这可能包含一个或多个从 0 到 9 的数字，地区或城市代码放在圆括号——
     * 对不使用地区或城市代码的国家（地区），则省略该组件。</p>
     * <p><b>电话号码：</b>这包含从 0 到 9 的一个或多个数字 </p>
     * @param isNull    检验此字段是否可以为空 true不可为空，false可以为空
     * @return 验证成功返回""，验证失败返回错误信息
     */
    public static String checkPhone(String phone, boolean isNull) {
        String regex = "(\\+\\d+)?(\\d{3,4}\\-?)?\\d{7,8}$";
        return commonRegex(regex, phone, "固定电话号码", isNull);
    }

    /**
     * 验证密码
     *
     * @param password      密码由6-16位大小写字母、数字和下划线组成
     * @param isNull        检验此字段是否可以为空 true不可为空，false可以为空
     * @return 验证成功返回""，验证失败返回错误信息
     */
    public static String checkPassword(String password, boolean isNull) {
        String regex = "^[0-9a-zA-Z_]{6,16}$";
        return commonRegex(regex, password, "密码", isNull);
    }

    /**
     * 验证URL地址
     *
     * @param url       格式：http://blog.csdn.net:80/xyang81/article/details/7705960? 或 http://www.csdn.net:80
     * @param isNull    检验此字段是否可以为空 true不可为空，false可以为空
     * @return 验证成功返回""，验证失败返回错误信息
     */
    public static String checkURL(String url, boolean isNull) {
        String regex = "(https?://(w{3}\\.)?)?\\w+\\.\\w+(\\.[a-zA-Z]+)*(:\\d{1,5})?(/\\w*)*(\\??(.+=.*)?(&.+=.*)?)?";
        return commonRegex(regex, url, "URL地址", isNull);
    }

    public static String commonRegex(String regex, String value, String label, boolean isNull){
        String result = checkEmpty(value, "URL地址", isNull);
        if (StringUtils.isNotEmpty(result)){
            return result;
        }

        if (StringUtils.isNotEmpty(value)){
            if (!Pattern.matches(regex,value)){
                return label + "格式错误";
            }
        }
        return "";
    }

    /**
     * 检测是否为空（如果isNull为true则value不能为空，如果isNull为false则value可以为空）
     *
     * @param value     输入的字段
     * @param label     输入的字段名称
     * @param isNull    检验此字段是否可以为空 true不可为空，false可以为空
     * @return 验证成功返回""，验证失败返回错误信息
     */
    public static <T> String checkEmpty(T value, String label, boolean isNull){
        if (isNull){
            if (value == null || StringUtils.isEmpty(value.toString())){
                return label + "不能为空";
            }
        }
        return "";
    }

    public static Boolean compareListStr(List list1, List list2){
        if (CollectionUtils.isEmpty(list1)){
            if (CollectionUtils.isEmpty(list2)){
                return true;
            }else {
                return false;
            }
        }else {
            if (CollectionUtils.isEmpty(list2)){
                return false;
            }else {
                return list1.containsAll(list2);
            }
        }
    }

    /**
     * 校验是否相等
     *
     * @param type     类型
     * @param paramNum 传参数值
     * @param backNum  后台数值
     */
    public static boolean checkIsEqual(String type, double paramNum, double backNum) {
        if (BigDecimal.valueOf(paramNum).compareTo(BigDecimal.valueOf(backNum)) != 0) {
            throw new RuntimeException(type + " 计算结果不一致。结果为:" + BigDecimal.valueOf(backNum).stripTrailingZeros().toPlainString());
        }
        return true;
    }

    /**
     * 校验是否相等
     *
     * @param type     类型
     * @param paramNum 传参数值
     * @param backNum  后台数值
     */
    public static boolean checkIsEqual2(String type, BigDecimal paramNum, BigDecimal backNum) {
        if (paramNum.compareTo(backNum) != 0) {
            throw new RuntimeException(type + " 计算结果不一致。结果为:" + backNum.stripTrailingZeros().toPlainString());
        }
        return true;
    }

}
